package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.*;
import com.tanhua.model.domain.Question;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.dto.RecommendUserDto;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.NearUserVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.TodayBest;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class TanhuaService {
    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private QuestionApi questionApi;

    @Autowired
    private HuanXinTemplate template;

    @DubboReference
    private UserLikeApi userLikeApi;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private MessagesService messagesService;

    @DubboReference
    private UserLocationApi userLocationApi;

    @DubboReference
    private VisitorsApi visitorsApi;

    //指定默认数据
    @Value("${tanhua.default.recommend.users}")
    private String recommendUser;

    public TodayBest todayBest() {
        Long userId = UserHolder.getUserId();
        RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(userId);
        if (recommendUser == null) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(1L);
            recommendUser.setScore(99d);
        }

        UserInfo userInfo = userInfoApi.findById(recommendUser.getUserId());
        TodayBest vo = TodayBest.init(userInfo, recommendUser);

        return vo;
    }

    public PageResult recommendation(RecommendUserDto dto) {
        //获取用户Id
        Long userId = UserHolder.getUserId();
        //调用recommendUserApi中分页方法,传入(page,pagesize,userId),获取动态分页数据
        PageResult pr = recommendUserApi.queryRecommendUserList(dto.getPage(), dto.getPagesize(), userId);
        //获取分页数据中的用户列表,强转成RecommendUser集合
        List<RecommendUser> items = (List<RecommendUser>) pr.getItems();
        //判断一下用户数据列表是否为空
        if (items == null) {
            //为空直接返回分页数据
            return pr;
        }
        //提取所有的用户id
        List<Long> ids = CollUtil.getFieldValues(items, "userId", Long.class);
        //构建查询条件,批量查询所有用户详情
        UserInfo userInfo=new UserInfo();
        userInfo.setAge(dto.getAge());
        userInfo.setGender(dto.getGender());

        Map<Long, UserInfo> map = userInfoApi.findByIds(ids, userInfo);
        //循环推荐的列表数据,构建vo对象
        List<TodayBest> list = new ArrayList<>();
        for (RecommendUser item : items) {
            //根据键userid,获取值userinfo
            UserInfo info = map.get(item.getUserId());
            if(info!=null){
                //info转化vo对象
                TodayBest vo = TodayBest.init(info, item);
                list.add(vo);
            }
        }
        pr.setItems(list);
        return pr;
    }

    public TodayBest personalInfo(Long id) {
        //根据推荐人id获取推荐人详情
        UserInfo userInfo = userInfoApi.findById(id);
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        RecommendUser user=recommendUserApi.queryByUserId(id,userId);
        //构造访客数据,调用api保存
        Visitors visitors=new Visitors();
        visitors.setUserId(id);
        visitors.setVisitorUserId(UserHolder.getUserId());
        visitors.setFrom("首页");
        visitors.setDate(System.currentTimeMillis());
        visitors.setVisitDate(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        visitors.setScore(user.getScore());
        visitorsApi.save(visitors);
        //构造返回值
        TodayBest vo = TodayBest.init(userInfo, user);
        return vo;
    }

    public String strangerQuestions(Long userId) {
        //调用api,根据userId查询txt
        Question question = questionApi.findByUserId(userId);
        return question==null ? "你喜欢编程吗?":question.getTxt();
    }

    public void replyQuestions(Long userId, String reply) {
        //构造消息数据
        Long toUserId = UserHolder.getUserId();
        UserInfo userInfo = userInfoApi.findById(toUserId);
        Map map=new HashMap();
        map.put("userId",toUserId);
        map.put("huanXinId", Constants.HX_USER_PREFIX+toUserId);
        map.put("nickname",userInfo.getNickname());
        map.put("strangerQuestions",strangerQuestions(userId));
        map.put("reply",reply);
        String s = JSON.toJSONString(map);
        //调用template对象,发送消息
        Boolean aBoolean = template.sendMsg(Constants.HX_USER_PREFIX + userId, s);
        if(!aBoolean){
            throw new BusinessException(ErrorResult.error());
        }
    }
    //推荐用户列表
    public List<TodayBest> queryCardsList() {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //调用推荐api,查询数据列表,排查喜欢/不喜欢
        List<RecommendUser> list=recommendUserApi.queryCardsList(userId,10);
        //判断列表是否为空
        if(CollUtil.isEmpty(list)){
            //为空返回默认数据
            list=new ArrayList<>();
            String[] ids = recommendUser.split(",");
            for (String id : ids) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(Convert.toLong(id));
                recommendUser.setToUserId(userId);
                recommendUser.setScore(RandomUtil.randomDouble(60, 90));
                list.add(recommendUser);
            }
        }
        //不为空,创建vo
        List<Long> userIdList = CollUtil.getFieldValues(list, "userId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIdList, null);
        List<TodayBest> vos=new ArrayList<>();
        for (RecommendUser user : list) {
            UserInfo userInfo = map.get(user.getUserId());
            if(userInfo!=null){
                TodayBest vo = TodayBest.init(userInfo, user);
                vos.add(vo);
            }
        }
        return vos;
    }

    public void love(Long likeUserId) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //调用api,根据条件查询对象
        Boolean aBoolean = userLikeApi.saveOrUpdate(userId, likeUserId, true);
        //判断是否为true
        if(!aBoolean){
            //操作失败抛异常
            throw new BusinessException(ErrorResult.error());
        }
        //操作redis,写入喜欢数据,删除不喜欢
        redisTemplate.opsForSet().remove(Constants.USER_NOT_LIKE_KEY+userId,likeUserId.toString());
        redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY+userId,likeUserId.toString());
        //判断是不是双向喜欢
        if(isLike(likeUserId,userId)){
            //如果是,添加好友
            messagesService.contacts(likeUserId);
        }

    }

    public Boolean isLike(Long userId,Long likeUserId){
        //判断redis里是否存在喜欢
        String key=Constants.USER_LIKE_KEY+userId;
        return redisTemplate.opsForSet().isMember(key,likeUserId.toString());
    }

    public void unlove(Long likeUserId) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //调用api,根据条件查询对象
        Boolean aBoolean = userLikeApi.saveOrUpdate(userId, likeUserId, false);
        //判断是否为true
        if(!aBoolean){
            //操作失败抛异常
            throw new BusinessException(ErrorResult.error());
        }
        //操作redis,写入喜欢数据,删除不喜欢
        redisTemplate.opsForSet().add(Constants.USER_NOT_LIKE_KEY+userId,likeUserId.toString());
        redisTemplate.opsForSet().remove(Constants.USER_LIKE_KEY+userId,likeUserId.toString());

    }

    public List<NearUserVo> queryNearUser(String gender, String distance) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //调用api,查询附近人的userId列表
        List<Long> userIds = userLocationApi.queryNearUser(userId, Double.valueOf(distance));
        //判断列表是否为空
        if(CollUtil.isEmpty(userIds)){
            return new ArrayList<>();
        }
        //调用userInfoApi查询详情
        UserInfo userInfo=new UserInfo();
        userInfo.setGender(gender);
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, userInfo);
        //循环遍历userIds列表,转化成vo
        List<NearUserVo> vos=new ArrayList<>();
        for (Long id : userIds) {
            if(id==userId){
                continue;
            }
            UserInfo info = map.get(id);
            if(info!=null){
                NearUserVo vo = NearUserVo.init(info);
                vos.add(vo);
            }
        }
        //构造返回值
        return vos;
    }


    /*public PageResult recommendation(RecommendUserDto dto) {
        //获取用户Id
        Long userId = UserHolder.getUserId();
        //调用recommendUserApi中分页方法,传入(page,pagesize,userId),获取动态分页数据
        PageResult pr = recommendUserApi.queryRecommendUserList(dto.getPage(), dto.getPagesize(), userId);
        //获取分页数据中的用户列表,强转成RecommendUser集合
        List<RecommendUser> items = (List<RecommendUser>) pr.getItems();
        //判断一下用户数据列表是否为空
        if (items == null) {
            //为空直接返回分页数据
            return pr;
        }

        //循环用户列表
        List<TodayBest> list = new ArrayList<>();
        for (RecommendUser item : items) {
            //获取每一个用户的id
            Long recommendUserId = item.getUserId();
            //根据用户id获取用户对象
            UserInfo userInfo = userInfoApi.findById(recommendUserId);
            //判断用户是否为null
            if (userInfo != null) {
                //不为null,判断是否符合条件
                if (dto.getGender() != null && !dto.getGender().equals(userInfo.getGender())) {
                    continue;
                }
                if (dto.getAge() != null && dto.getAge() < userInfo.getAge()) {
                    continue;
                }
                //使用TodayBest.init方法将userInfo转化成item
                TodayBest vo = TodayBest.init(userInfo, item);

                list.add(vo);
            }
        }

        //list存到pr里
        pr.setItems(list);
        return pr;
    }*/

}
